import { _decorator, Node, AssetManager, Prefab, instantiate } from 'cc';
import { GameCore } from '../../Base/Class';
import { Constructor, NewClass, setClassName } from '../../Base/Global';
import { Singleton } from '../../Base/Singleton';
import { AssetInfo } from '../ResourceLoad/base/AssetInfo';
import { AssetCollectionInfo } from '../ResourceLoad/_c/AssetCollectionInfo';
import { ResourceLoadSpace } from '../ResourceLoad/_h/Index';
import { UIData } from './base/UIData';
import { UIComponent } from "./UIComponent";
import { UIComponentCreateFactor } from './UIComponentCreateFactor';
import { UIComponentProxyManager } from './UIComponentProxyManager';

export class UIComponentProxy extends GameCore.ClassBase
{
    private tempComponets : UIComponent = null;
    private mainAssetInfo : AssetInfo = null;
    private oComponentNode : Node = null;
    private components = new Array<UIComponent>();
    private _loadDone:boolean = false;
    public get loadDone() : boolean {return this._loadDone;}
    public set loadDone(isDone : boolean) {this._loadDone = isDone; this.UpdateView();}
    
    private factor : UIComponentCreateFactor = null;
    private parent : Node = null;
    private dataList : Array<UIData> = null;
    private oClassFunc : Constructor<UIComponent> = null;

    private collection : ResourceLoadSpace.IAssetCollectionInfo = null;
    public GetAssetBundle(assetInfo : AssetInfo) : AssetManager.Bundle
    {
        if(this.collection != null)
        {
            return this.collection.GetAsset(assetInfo);
        }   
        return null;
    }

    public SetAssetCollection(collection : ResourceLoadSpace.IAssetCollectionInfo)
    {
        this.collection = collection;
    }

    public GetMainAssetInfo() : AssetInfo
    {
        return this.mainAssetInfo;
    }

    //机制函数 
    private SetFactor(factor: UIComponentCreateFactor) {
        this.factor = factor;
    }

    private SetParent(parent : Node)
    {
        this.parent = parent;
    }

    // public fromPool<T>(cls: { new() : T}): T {
    //         return new cls();
    // }

    public Init(cls: Constructor<UIComponent>, oParent : Node, oFactor: UIComponentCreateFactor, oComponentNode? : Node)
    {
        Singleton.Instance(UIComponentProxyManager).RegisterComponentProxy(this);
        this.SetParent(oParent);
        this.SetFactor(oFactor);
        this.tempComponets = NewClass(this.oClassFunc);
        this.oComponentNode = oComponentNode;
        this.oClassFunc = cls;
        this.RequestAsset();
    }

    private SetComponentNode(oComponentNode : Node)
    {
        this.oComponentNode = oComponentNode;
        this.oComponentNode.setParent(this.parent);
        this.oComponentNode.active = false;
        this.loadDone = true;
    }

    private RequestAsset()
    {
        if(this.loadDone)
        {
            return;
        }

        // 增加到下载列表中
        if(this.oComponentNode != null)
        {
            this._loadDone = true;
            return;
        }

        var assetInfo = this.tempComponets.GetAssetInfo();
        if(assetInfo == null){
            console.error("can not find assetInfo ! " + this.tempComponets.className);
            return;
        }
        this.mainAssetInfo = assetInfo;

        var collection = NewClass(AssetCollectionInfo);
        collection.AddAssetInfo(assetInfo);

        // 等到下载列表完成以后进行初始化
        var preloadAssetInfos = this.tempComponets.GetPreloadAssetInfos();
        if(preloadAssetInfos != null)
        {
            preloadAssetInfos.forEach((info)=>{
                collection.AddAssetInfo(info);
            });
        }

        var instanceId = this.instanceId;
        collection.AddLoadDoneCallBack((data : any, colection : AssetCollectionInfo)=>{
            var instanceId = data as number;
            var oProxy = Singleton.Instance(UIComponentProxyManager).GetComponentProxy<UIComponentProxy>(instanceId);
            if(oProxy != null)
            {
                oProxy.SetAssetCollection(colection);
                var assetInfo = oProxy.GetMainAssetInfo();
                var bundle = oProxy.GetAssetBundle(assetInfo);
                if(bundle != null)
                {
                    bundle.load<Prefab>(assetInfo.assetName, (err, asset)=>
                    {
                        if(err != null)
                        {
                            console.error(err);
                        }

                        var oProxy = Singleton.Instance(UIComponentProxyManager).GetComponentProxy<UIComponentProxy>(instanceId);
                        if(oProxy.instanceId == instanceId)
                        {
                            oProxy.SetAssetCollection(collection);
                            oProxy.SetComponentNode(instantiate(asset) as Node);
                        }
                        else
                        {
                            asset.destroy();
                        }
                    });
                }
                else
                {
                    console.error("can not find bundle ! bundleName: " + assetInfo.assetBundleName + "  className:" + oProxy.tempComponets.className);
                }
            }
            else
            {
                collection.Release();
            }

        }, instanceId);
        collection.StartRequestAsset();
    }

    private ResetComponentSize()
    {
        for(var i = 0; i < this.dataList.length; i++)
        {
            var obj : UIComponent = null;
            if(i >= this.components.length)
            {
                var obj = this.CloneComponet();
                this.components.push(obj);
            }
            else
            {
                obj = this.components[i];
            }
            obj.SetEffective(true);
        }

        for(var index = this.dataList.length - 1; index < this.components.length; index++)
        {
            var obj = this.components[i];
            obj.SetEffective(false);
        }
    }

    private CloneComponet() : UIComponent
    {
        var obj = this.tempComponets != null ? this.tempComponets : NewClass(this.oClassFunc);
        // 这里还要做一个初始化，将所有的natureComponent资源复制到obj里 在创建的时候也要设置父物体
        obj.SetAssetCollection(this.collection);
        obj.SetParent(this.parent);
        obj.Init(instantiate(this.oComponentNode) as Node);
        obj.OnLoadUIMap();
        obj.OnLoad();

        this.tempComponets = null;
        return obj;
    }

    public Destory() 
    {
        // 防止销毁不正确
        if(!this.factor.CheckDestroyingProxyIsThis(this))
        {
            console.error("destory error! if you want to destory this proxy! you shoult be call factor::DestroyProxy func to do what you want to do!");
            return;
        }

        Singleton.Instance(UIComponentProxyManager).UnRegisterComponentProxy(this);
        // 销毁
        this.components.forEach((comp : UIComponent)=>{
            comp.OnDestroySelf();
        });
        this.components.slice();
    }

    // 外部可使用的接口
    public UpdateView()
    {
        if(!this.loadDone)
        {
            return;
        }
        this.ResetComponentSize();
        for(var i = 0; i < this.dataList.length; i++)
        {
            var oData = this.dataList[i];
            var obj = this.components[i];
            obj.OnUpdateComponent(oData);
        }
    }

    public SetData(dataList : Array<UIData>)
    {
        this.dataList = dataList;
        if(this.dataList == null)
        {
            this.dataList = new Array<UIData>();
        }
        this.UpdateView();
    }

    public GetComponent<T extends UIComponent>(index : number) : T
    {
        if(0 <= index && index < this.dataList.length)
        {
            return this.components[index] as T
        }
        return null;
    }
}
setClassName(UIComponentProxy, "UIComponentProxy")